#include <graphics.h>
#include <sstream>
#include "player.h"
#include "enemy.h"
#include "bullet.h"
#include "constants.h"
#include "ResourceManager.h"

IMAGE img_background;

#pragma comment(lib, "MSIMG32.LIB")

void TryGenerateEnemy(std::vector<std::unique_ptr<Enemy>>& enemy_list, int interval){
    static int counter = 0;
    if((++counter) > interval){
        enemy_list.emplace_back(std::make_unique<Enemy>("D:\\Clion Project\\TeyvatSurvivor\\img", 6, 45));
        counter = 0;
    }
}

void UpdateBullets(std::vector<std::unique_ptr<Bullet>>& bullet_list, Player& player, int interval){
    static bool initial = true;
    static int counter = 0;
    if(initial){
        for(int i=0;i<3;i++){
            bullet_list.emplace_back(std::make_unique<Bullet>());
            initial = false;
        }
    }else{
        if(bullet_list.size()<3){
            if((++counter) > interval){
                bullet_list.emplace_back(std::make_unique<Bullet>());
                counter = 0;
            }
        }
    }

    const double RADIAL_SPEED = 0.0045;     //径向速度
    const double TANGENT_SPEED = 0.0055;    //切向速度
    double radian_interval = 2 * 3.1415926 / 3;    //子弹之间的弧度间隔
    POINT player_position  = player.getPlayerPos();
    double radius = 100 + 25 * sin(GetTickCount() * RADIAL_SPEED);
    int count = 0;
    for(size_t i = 0; i < bullet_list.size(); i++){
        auto& bullet = bullet_list[i];
        double radian = GetTickCount() * TANGENT_SPEED + radian_interval * count;
        count++;
        bullet->bullet_pos.x = player_position.x + player.getPlayerWidth() / 2 + (int)(radius * sin(radian));
        bullet->bullet_pos.y = player_position.y + player.getPlayerHeight() / 2 + (int)(radius * cos(radian));
    }

}

int main() {
    ResourceManager::LoadResources("D:\\Clion Project\\TeyvatSurvivor\\img", 6, "player");
    ResourceManager::LoadResources("D:\\Clion Project\\TeyvatSurvivor\\img", 6, "enemy");

    Player player("D:\\Clion Project\\TeyvatSurvivor\\img", 6, 45);
    std::vector<std::unique_ptr<Enemy>> enemy_list;
    std::vector<std::unique_ptr<Bullet>> bullet_list;

	initgraph(g_window_width, g_window_hight);
	
	bool running = true;

	ExMessage msg;

	BeginBatchDraw();

	loadimage(&img_background, _T("D:\\Clion Project\\TeyvatSurvivor\\img\\background.png"));

	while (running) {

		DWORD start_time = GetTickCount();

		while (peekmessage(&msg)) {
            player.ProcessEvent(msg);
		}

        player.Move();
        UpdateBullets(bullet_list,player,45);
        TryGenerateEnemy(enemy_list, 100);

        for(size_t i = 0; i < enemy_list.size(); ){             //不写 i++
            auto& enemy = enemy_list[i];
            enemy->Move(player);

            //检测敌人是否与玩家碰撞
            if(enemy->CheckPlayerCollision(player)){
                MessageBox(GetHWnd(), _T("you died"), _T("game over"), MB_OK);
                running = false;
                break;
            }

            //检测敌人是否与子弹碰撞
            for(size_t j = 0; j < bullet_list.size(); ){
                auto& bullet = bullet_list[j];
                if(enemy->CheckBulletCollision(*bullet)){
                    enemy->Hurt();

                    //删除碰撞子弹
                    std::swap(bullet, bullet_list.back());
                    bullet_list.pop_back();
                }else{
                    j++;
                }
            }

            //删除被击中敌人
            if(!enemy->CheckAlive()){
                std::swap(enemy, enemy_list.back());
                enemy_list.pop_back();
                // 不递增 i，因为当前元素已被替换
            }else{
                i++;    // 只有未删除元素时才递增
            }
        }


		cleardevice();

        //画面渲染
		putimage(0, 0, &img_background);

        player.Draw(1000 / 144);
        for(auto& bullet : bullet_list){
            bullet->Draw();
        }
        for(auto& enemy : enemy_list){
            enemy->Draw(1000 / 144);
        }

		FlushBatchDraw();

		DWORD end_time = GetTickCount();
		DWORD delta_time = end_time - start_time;
		if (delta_time < (1000 / 144)) {
			Sleep(1000 / 144 - delta_time);
		}

	}

	EndBatchDraw();

	return 0;
}